package com.myk.game.heroscuffle.game;

import com.myk.game.heroscuffle.data.GameParam;
import com.myk.game.heroscuffle.events.GameEvent_RoundEnd;
import com.myk.game.heroscuffle.events.GameEvent_RoundStart;
import com.myk.game.heroscuffle.utils.Num2CnUtil;

/**
 * 游戏核心类
 */
public class Game {

    public GameExecutor executor; //执行线程
    public GameUI ui; //游戏界面
    public HeroPool pool;//上场的英雄集合容器
    public GameEvents events; //游戏过程事件中心
    public HateRecorder recorder; //仇恨or恩情记录中心（记录每回合谁对谁进行了伤害或者治疗保护）
    public int round; //回合计数

    public Game(GameUI gameUI) {
        this.ui = gameUI;
        this.executor = new GameExecutor(this);
    }

    //进入首页
    public void initHome() {
        executor.submit(() -> {
            ui.clearMsg();
            ui.resetCtrl();
            ui.printMsg("欢迎来到《英雄乱斗》");
            ui.sleepNormal();
            ui.printlnMsg("让一群可爱的英雄互相战斗！");
            ui.sleepNormal();
            ui.printlnMsg("请不要太过激动，");
            ui.sleepNormal();
            ui.printlnMsg("这只是个无聊的游戏。");
            ui.sleepNormal();
            ui.setTip("点击“开始游戏”按钮进行游戏");
            ui.addCtrl("开始", this::startGame);
            ui.addCtrl("帮助", ui::showHelpDialog);
            ui.addCtrl("记录", ui::showRecordDialog);
            ui.addCtrl("退出", ui::exitApp);
        });
    }

    //开始游戏
    private void startGame() {
        executor.submit(() -> {
            ui.clearMsg();
            ui.resetCtrl();
            ui.printMsg("【游戏开始】");
            pool = new HeroPool(this);
            events = new GameEvents();
            recorder = new HateRecorder();
            round = 0;
            ui.sleepNormal();
            ui.printlnMsg("随机召唤" + GameParam.GAME_HERO_COUNT + "名英雄：");
            pool.summonHeroes(GameParam.GAME_HERO_COUNT); //随机新召唤指定数量的英雄上场
            ui.sleepShortly();
            pool.printOriginHeroes();
            if (GameParam.PLAYER_SELECT_SWITCH) {
                selectPlayerHero(0);  //玩家选择该局游戏操作的英雄
            }
            else {
                ui.setTip("是否开始这场乱斗？");
                ui.resetCtrl();
                ui.addCtrl("开始", this::roundStart);
                ui.addCtrl("重开", this::startGame);
                ui.addCtrl("终止", this::finishGame);
            }
        });
    }

    //选择玩家操作的英雄
    private void selectPlayerHero(final int index) {
        executor.submit(() -> {
            Hero curSelectHero = pool.getHeroFromList(index);
            ui.setTip("请选择你要操控的英雄,当前待选:" + curSelectHero.getDetailDescription());
            ui.resetCtrl();
            ui.addCtrl("选中", () -> executor.submit(() -> {
                ui.resetCtrl();
                ui.printlnMsg("玩家操控" + curSelectHero.getObviousName() + "。");
                curSelectHero.state.setPlayer();
                ui.sleepNormal();
                roundStart();
            }));
            ui.addCtrl("切换", () -> {
                int newIndex = index + 1;
                if (newIndex == GameParam.GAME_HERO_COUNT) {
                    newIndex = 0;
                }
                selectPlayerHero(newIndex);
            });
            ui.addCtrl("重开", this::startGame);
            ui.addCtrl("终止", this::finishGame);
        });
    }

    //回合开始
    private void roundStart() {
        executor.submit(() -> {
            round++;
            ui.resetCtrl();
            ui.printlnMsg("[第" + Num2CnUtil.convert2cn(round) + "回合开始]：");
            pool.clearAllActioned(); //重置所有英雄行动状态
            ui.sleepFast();
            events.onRoundStart.sendRun(new GameEvent_RoundStart(round));//回合开始事件通知
            heroActionStart(); //随机选择一名英雄开始行动
        });
    }

    //随机选择一名英雄开始行动
    private void heroActionStart() {
        executor.submit(() -> {
            pool.chooseCurActionHero();//随机选择一名英雄准备行动
            pool.curActionHero.preAction(); //通知英雄准备开始回合
            if (pool.curActionHero.state.isAlive) {
                if (pool.curActionHero.state.isPlayer) {
                    playerSelectAction(); //玩家选择行动方式
                }
                else {
                    autoSelectAction(); //ai自动选择行动方式
                }
            }
            else {
                checkGameOver();
            }
        });
    }

    //系统自动选择行动
    private void autoSelectAction() {
        executor.submit(() -> {
            ui.resetCtrl();
            pool.curActionHero.autoActionSelect(); //英雄自己选择行动方式
            checkGameOver();
        });
    }

    //玩家选择行动方式
    private void playerSelectAction() {
        executor.submit(() -> {
            ui.resetCtrl();
            ui.setTip("请选择" + pool.curActionHero.getObviousName() + "的行为！");
            ui.addCtrl("普攻", this::playerSelectAttack);
            if (pool.curActionHero.SKILLS.size() > 0) {
                ui.addCtrl("技能", this::playerSelectSkill);
            }
            ui.addCtrl("查看", pool::showHeroesCurrentInfoDialog);
            ui.addCtrl("终止", this::finishGame);
        });
    }

    //玩家选择了普攻
    private void playerSelectAttack() {
        executor.submit(() -> {
            Attacked preAttacked = pool.curActionHero.autoSelectAttacked();
            playerSelectedAttacked(preAttacked);
        });
    }

    //确认攻击目标
    private void playerSelectedAttacked(Attacked preAttacked) {
        executor.submit(() -> {
            ui.resetCtrl();
            ui.setTip("是否打算攻击" + preAttacked.getTarget().getObviousName() + "？");
            ui.addCtrl("确认", () -> executor.submit(() -> {
                ui.resetCtrl();
                pool.curActionHero.onAcceptPlayerAttackAction(preAttacked);
                checkGameOver();
            }));
            if (pool.getAliveCount() > 2) { //存活英雄要大于2否则没得选啊
                ui.addCtrl("更换", () -> {
                    Hero antherPreAttacked = pool.getAnyoneAliveHero(pool.curActionHero, preAttacked.getTarget());
                    playerSelectedAttacked(new Attacked(antherPreAttacked, "遵从指定攻击"));
                });
            }
            ui.addCtrl("返回", this::playerSelectAction);
        });
    }

    //玩家选择技能
    private void playerSelectSkill() {
        executor.submit(() -> {
            ui.resetCtrl();
            ui.setTip("请选择你要使用的技能！");
            Hero hero = pool.curActionHero; //当前行动的角色
            for (Skill skill : hero.SKILLS) { //根据当前角色技能显示控制按钮
                ui.addCtrl(skill.getDetailName(), skill.isReady(), () -> executor.submit(() -> {
                    ui.resetCtrl();
                    hero.useSkill(skill);
                    checkGameOver();
                }));
            }
            ui.addCtrl("返回", this::playerSelectAction);
        });
    }

    //判断回合是否结束
    private void checkRoundOver() {
        executor.submit(() -> {
            if (pool.isAllActioned()) {
                roundEnd();
            }
            else {
                heroActionStart();
            }
        });
    }

    //判断游戏是否结束
    private void checkGameOver() {
        executor.submit(() -> {
            ui.sleepFast();
            if (pool.getAliveCount() > 1) {
                checkRoundOver();
            }
            else {
                gameOver();
            }
        });
    }

    //回合结束
    private void roundEnd() {
        executor.submit(() -> {
            ui.resetCtrl();
            ui.printlnMsg("第" + Num2CnUtil.convert2cn(round) + "回合结束：");
            events.onRoundEnd.sendRun(new GameEvent_RoundEnd(round));
            ui.sleepFast();
            pool.printAliveHeroes(); //回合结束只打印存活下来的英雄
            if (GameParam.PLAYER_SELECT_SWITCH) {
                ui.setTip("点击继续开始下一回合");
                ui.addCtrl("继续", this::roundStart);
                ui.addCtrl("重开", this::startGame);
                ui.addCtrl("终止", this::finishGame);
            }
            else {
                roundStart();
            }
        });
    }

    //游戏结束
    private void gameOver() {
        executor.submit(() -> {
            ui.resetCtrl();
            ui.printlnMsg("游戏结束，" + pool.curActionHero.getObviousName() + "活到了最后！");
            ui.sleepNormal();
            if (GameParam.PLAYER_SELECT_SWITCH){
                ui.printlnMsg("玩家" + (pool.curActionHero.state.isPlayer ? "获得胜利！" : "挑战失败！"));
                ui.sleepNormal();
            }
            ui.setTip("请选择您的操作...");
            ui.addCtrl("保存", ui::saveRecordData);
            ui.addCtrl("重开", this::startGame);
            ui.addCtrl("首页", this::initHome);
        });
    }

    //强制终止游戏
    private void finishGame() {
        executor.submit(() -> {
            ui.resetCtrl();
            ui.printlnMsg("本局游戏被强制终止，记录不予保存。");
            ui.sleepNormal();
            ui.setTip("请选择您的操作...");
            ui.addCtrl("重开", this::startGame);
            ui.addCtrl("首页", this::initHome);
        });
    }

}
